package com.bidevalution.support.compare;

import lombok.extern.log4j.Log4j2;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * 相似度计算模型
 */
@Log4j2
public class Model {

	/**
	 * input:docList1,docList2 主方法入口及控制器
	 */
	public double getAvgSimilar(List<String> docList1, List<String> docList2) {
		int i, j, n1, n2;
		double[] similarArr;
		int[] locArr;
		double max, temp;
		int loc;
		n1 = docList1.size();
		n2 = docList2.size();
		similarArr = new double[n1];
		locArr = new int[n1];
		StringHandler sh = new StringHandler();
		//将句子分词成数组
		List<List<String>> arrayList1 = sh.stringListToArrayList(docList1);
		List<List<String>> arrayList2 = sh.stringListToArrayList(docList2);
		for (i = 0; i < n1; i++) {
			max = 0.0;
			temp = 0.0;
			loc = 0;
			for (j = 0; j < n2; j++) {
				try {
					temp = getSimilar(arrayList1.get(i), arrayList2.get(j));
				} catch (IOException e) {
					temp = 0.0;
                    log.error(e.getMessage(), e);
				}
				if (temp > max) {
					max = temp;
					loc = j;
				}
			}
			similarArr[i] = max;
			locArr[i] = loc;
		}
		double sum = 0.0;
		int k,n;
		n = docList1.size();
		for(k = 0;k < n;k++){
			sum += similarArr[k];
		}
		return sum / n;
	}

	/**
	 * input:str1,str2 计算2个字符串之间的相似度
	 * @param list1 str1分词后的list
	 * @param list2 str2分词后的list
	 * @return
	 * @throws IOException
	 */
	private double getSimilar(List<String> list1, List<String> list2) throws IOException {

		double ret = 0.0;
		// 创建向量空间模型，使用map实现，主键为词项，值为长度为2的数组，存放着对应词项在字符串中的出现次数
		Map<String, int[]> vectorSpace = new HashMap<String, int[]>();
		// 为了避免频繁产生局部变量，所以将itemCountArray声明在此
		int[] itemCountArray = null;
		Iterator iter;
		// 向量1的模
		double vector1Modulo = 0.00;
		// 向量2的模
		double vector2Modulo = 0.00;
		// 向量积
		double vectorProduct = 0.00;
		
		int i,n;
		n = list1.size();
		for (i = 0; i < n; ++i) {
			if (vectorSpace.containsKey(list1.get(i))) {
				++(vectorSpace.get(list1.get(i))[0]);
			} else {
				itemCountArray = new int[2];
				itemCountArray[0] = 1;
				itemCountArray[1] = 0;
				vectorSpace.put(list1.get(i), itemCountArray);
			}
		}
		
		//对str2处理
		n = list2.size();
		for (i = 0; i < n; ++i) {
			if (vectorSpace.containsKey(list2.get(i))) {
				++(vectorSpace.get(list2.get(i))[1]);
			} else {
				itemCountArray = new int[2];
				itemCountArray[0] = 0;
				itemCountArray[1] = 1;
				vectorSpace.put(list2.get(i), itemCountArray);
			}
		}

		//计算相似度
		iter = vectorSpace.entrySet().iterator();
		while (iter.hasNext()) {
			Map.Entry entry = (Map.Entry) iter.next();
			itemCountArray = (int[]) entry.getValue();
			vector1Modulo += itemCountArray[0] * itemCountArray[0];
			vector2Modulo += itemCountArray[1] * itemCountArray[1];
			vectorProduct += itemCountArray[0] * itemCountArray[1];
		}
		vector1Modulo = Math.sqrt(vector1Modulo);
		vector2Modulo = Math.sqrt(vector2Modulo);
		// 返回相似度
		ret  = (vectorProduct / (vector1Modulo * vector2Modulo));
		return ret;
	}

}
